import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import threading
import queue
import os
import shutil
import re
import time
from translate import Translator

# 全局配置
MAX_WORKERS = os.cpu_count() or 4  # 确保至少4个线程
BATCH_SIZE = 100
TRANS_RETRIES = 1
TRANS_TIMEOUT = 5


class TranslationApp:
    def __init__(self, root):
        self.root = root
        self.root.title("文件名翻译工具")
        self.root.geometry("800x600")
        self.root.resizable(True, True)

        # 创建队列用于线程通信
        self.log_queue = queue.Queue()
        self.running = False
        self.file_count = 0  # 总文件数
        self.base_count = 0  # 基础名称数量
        self.progress_value = 0  # 当前进度值（0-100）
        self.last_progress_time = 0  # 上次更新进度条的时间

        self.create_widgets()
        self.setup_layout()
        self.update_ui()

    def create_widgets(self):
        # 源目录选择
        self.source_label = ttk.Label(self.root, text="源目录:")
        self.source_entry = ttk.Entry(self.root, width=50)
        self.source_button = ttk.Button(self.root, text="浏览", command=self.browse_source)

        # 目标目录选择
        self.target_label = ttk.Label(self.root, text="目标目录:")
        self.target_entry = ttk.Entry(self.root, width=50)
        self.target_button = ttk.Button(self.root, text="浏览", command=self.browse_target)

        # 配置信息
        self.config_frame = ttk.LabelFrame(self.root, text="配置")
        self.workers_label = ttk.Label(self.config_frame, text="工作线程:")
        self.workers_combo = ttk.Combobox(self.config_frame, width=5,
                                          values=[str(i) for i in range(1, MAX_WORKERS * 2 + 1)])
        self.workers_combo.set(str(MAX_WORKERS))
        self.batch_label = ttk.Label(self.config_frame, text="批量大小:")
        self.batch_entry = ttk.Entry(self.config_frame, width=8)
        self.batch_entry.insert(0, str(BATCH_SIZE))

        # 进度条
        self.progress_label = ttk.Label(self.root, text="进度:")
        self.progress_bar = ttk.Progressbar(self.root, orient="horizontal", length=600, mode="determinate")

        # 状态信息
        self.status_var = tk.StringVar(value="就绪")
        self.status_label = ttk.Label(self.root, textvariable=self.status_var)

        # 日志框
        self.log_label = ttk.Label(self.root, text="操作日志:")
        self.log_area = scrolledtext.ScrolledText(self.root, width=90, height=20, state="disabled")
        self.log_area.tag_config("info", foreground="blue")
        self.log_area.tag_config("error", foreground="red")

        # 控制按钮
        self.button_frame = ttk.Frame(self.root)
        self.start_button = ttk.Button(self.button_frame, text="开始翻译", command=self.start_translation)
        self.stop_button = ttk.Button(self.button_frame, text="停止", command=self.stop_translation, state="disabled")

    def setup_layout(self):
        # 源目录布局
        self.source_label.grid(row=0, column=0, padx=5, pady=5, sticky="e")
        self.source_entry.grid(row=0, column=1, padx=5, pady=5, sticky="we")
        self.source_button.grid(row=0, column=2, padx=5, pady=5)

        # 目标目录布局
        self.target_label.grid(row=1, column=0, padx=5, pady=5, sticky="e")
        self.target_entry.grid(row=1, column=1, padx=5, pady=5, sticky="we")
        self.target_button.grid(row=1, column=2, padx=5, pady=5)

        # 配置框架布局
        self.config_frame.grid(row=2, column=0, columnspan=3, padx=10, pady=10, sticky="we")
        self.workers_label.grid(row=0, column=0, padx=5, pady=5)
        self.workers_combo.grid(row=0, column=1, padx=5, pady=5)
        self.batch_label.grid(row=0, column=2, padx=5, pady=5)
        self.batch_entry.grid(row=0, column=3, padx=5, pady=5)

        # 进度条布局
        self.progress_label.grid(row=3, column=0, padx=5, pady=5, sticky="e")
        self.progress_bar.grid(row=3, column=1, padx=5, pady=5, sticky="we", columnspan=2)

        # 状态标签布局
        self.status_label.grid(row=4, column=0, columnspan=3, padx=5, pady=5)

        # 日志区域布局
        self.log_label.grid(row=5, column=0, padx=5, pady=5, sticky="nw")
        self.log_area.grid(row=6, column=0, columnspan=3, padx=10, pady=5, sticky="nsew")

        # 按钮框架布局
        self.button_frame.grid(row=7, column=0, columnspan=3, pady=10)
        self.start_button.grid(row=0, column=0, padx=20)
        self.stop_button.grid(row=0, column=1, padx=20)

        # 设置网格列权重
        self.root.columnconfigure(1, weight=1)
        self.root.rowconfigure(6, weight=1)

    def browse_source(self):
        path = filedialog.askdirectory(title="选择源目录")
        if path:
            self.source_entry.delete(0, tk.END)
            self.source_entry.insert(0, path)

    def browse_target(self):
        path = filedialog.askdirectory(title="选择目标目录")
        if path:
            self.target_entry.delete(0, tk.END)
            self.target_entry.insert(0, path)

    def log_message(self, message, level="info"):
        self.log_area.configure(state="normal")
        self.log_area.insert(tk.END, message + "\n", level)
        self.log_area.see(tk.END)
        self.log_area.configure(state="disabled")

    def update_ui(self):
        # 处理日志队列
        while not self.log_queue.empty():
            msg, level = self.log_queue.get_nowait()
            self.log_message(msg, level)

        # 每100ms检查一次更新
        self.root.after(100, self.update_ui)

    def update_progress(self):
        """定期更新进度条和状态信息"""
        # 更新进度条
        self.progress_bar["value"] = self.progress_value

        # 更新状态信息
        self.status_var.set(f"处理中: {self.progress_value:.1f}%")

        # 如果任务仍在运行，5秒后再次更新
        if self.running:
            self.root.after(5000, self.update_progress)

    def start_translation(self):
        source_dir = self.source_entry.get()
        target_dir = self.target_entry.get()

        if not source_dir or not target_dir:
            messagebox.showerror("错误", "请选择源目录和目标目录")
            return

        if not os.path.exists(source_dir):
            messagebox.showerror("错误", "源目录不存在")
            return

        try:
            max_workers = int(self.workers_combo.get())
            batch_size = int(self.batch_entry.get())
        except ValueError:
            messagebox.showerror("错误", "线程数和批量大小必须是整数")
            return

        # 确保目标目录存在
        os.makedirs(target_dir, exist_ok=True)

        # 更新UI状态
        self.running = True
        self.start_button.config(state="disabled")
        self.stop_button.config(state="enabled")
        self.log_area.configure(state="normal")
        self.log_area.delete(1.0, tk.END)
        self.log_area.configure(state="disabled")
        self.progress_bar["value"] = 0
        self.file_count = 0  # 重置文件计数
        self.base_count = 0  # 重置基础名称计数
        self.progress_value = 0  # 重置进度值
        self.status_var.set("正在启动翻译进程...")

        # 启动翻译线程
        threading.Thread(
            target=self.process_directory,
            args=(source_dir, target_dir, max_workers, batch_size),
            daemon=True
        ).start()

        # 启动进度更新
        self.update_progress()

    def stop_translation(self):
        self.running = False
        self.status_var.set("正在停止...")

    def preprocess_filename(self, filename):
        # 文件名预处理实现
        name, ext = os.path.splitext(filename)

        if name.upper().startswith("FX"):
            name = name[2:]

        name = name.replace('_', ' ')
        name = name.lstrip(' -')

        suffix = ""
        base_name = name
        match = re.search(r'(\s+\d{1,3})$', name)
        if match:
            suffix = match.group(1).strip()
            base_name = name[:match.start()].strip()

        return base_name, suffix, ext, filename

    class BatchTranslator:
        def __init__(self):
            self.translator = Translator(from_lang='en', to_lang='zh')
            self.lock = threading.Lock()

        def translate_batch(self, texts):
            for attempt in range(TRANS_RETRIES):
                try:
                    with self.lock:
                        return [self.translator.translate(text) for text in texts]
                except Exception as e:
                    if attempt < TRANS_RETRIES - 1:
                        time.sleep(1)
                    else:
                        return texts

    def file_processor(self, task_queue, translator, app, progress_per_file):
        while app.running:
            try:
                task = task_queue.get(timeout=1)
                if task is None:
                    break

                source_path, rel_path, target_dir, base_name, suffix, ext, original_filename = task
                translated_base = translator.translate_batch([base_name])[0]

                if suffix:
                    clean_name = f"{base_name} {suffix}"
                    translated_name = f"{translated_base} {suffix}"
                else:
                    clean_name = base_name
                    translated_name = translated_base

                new_filename = f"{clean_name}({translated_name}){ext}"
                target_path = os.path.join(target_dir, rel_path, new_filename)
                os.makedirs(os.path.dirname(target_path), exist_ok=True)
                shutil.copy2(source_path, target_path)

                # 更新进度（文件处理阶段：30% → 100%）
                app.progress_value += progress_per_file
                if app.progress_value > 100:
                    app.progress_value = 100

                task_queue.task_done()

            except queue.Empty:
                break
            except Exception as e:
                app.log_queue.put((f"文件处理错误: {str(e)}", "error"))
                app.progress_value += progress_per_file  # 即使出错也计入进度
                task_queue.task_done()

    def process_directory(self, source_dir, target_dir, max_workers, batch_size):
        try:
            start_time = time.time()
            self.log_queue.put(("开始扫描文件并准备多线程处理...", "info"))
            self.status_var.set("扫描文件中...")

            task_queue = queue.Queue()
            translator = self.BatchTranslator()

            # =================== 第一阶段：扫描文件 (0% → 10%) ===================
            # 收集文件信息
            file_count = 0
            base_names = set()
            for root, dirs, files in os.walk(source_dir):
                for filename in files:
                    source_path = os.path.join(root, filename)
                    rel_path = os.path.relpath(root, source_dir)
                    base_name, suffix, ext, orig_name = self.preprocess_filename(filename)

                    task_queue.put((
                        source_path,
                        rel_path,
                        target_dir,
                        base_name,
                        suffix,
                        ext,
                        orig_name
                    ))

                    base_names.add(base_name)
                    file_count += 1

            self.file_count = file_count  # 更新总文件数
            self.base_count = len(base_names)  # 更新基础名称数量
            self.progress_bar["maximum"] = 100  # 设置进度条最大值为100%

            # 扫描完成，更新进度到10%
            self.progress_value = 10
            self.log_queue.put((f"扫描完成，共发现 {file_count} 个文件, {self.base_count} 个基础名称", "info"))
            self.status_var.set(f"扫描完成: {file_count} 个文件")

            # =================== 第二阶段：批量翻译 (10% → 30%) ===================
            self.log_queue.put(("开始批量翻译基础名称...", "info"))
            self.status_var.set("批量翻译中...")

            # 计算每个基础名称的进度增量 (20% / 基础名称数量)
            progress_per_base = 20.0 / max(self.base_count, 1)

            all_bases = list(base_names)
            translated_bases = []
            for i in range(0, len(all_bases), batch_size):
                batch = all_bases[i:i + batch_size]
                translated_batch = translator.translate_batch(batch)
                translated_bases.extend(translated_batch)

                # 更新进度
                self.progress_value += progress_per_base * len(batch)
                if self.progress_value > 30:
                    self.progress_value = 30

            base_name_map = dict(zip(all_bases, translated_bases))
            translator.translate_batch = lambda texts: [base_name_map.get(text, text) for text in texts]

            # 批量翻译完成，确保进度到30%
            self.progress_value = 30
            self.log_queue.put((f"批量翻译完成，启动 {max_workers} 个工作线程...", "info"))
            self.status_var.set("处理文件中...")

            # =================== 第三阶段：文件处理 (30% → 100%) ===================
            # 计算每个文件的进度增量 (70% / 文件数量)
            progress_per_file = 70.0 / max(file_count, 1)

            # 创建工作线程
            workers = []
            for _ in range(max_workers):
                t = threading.Thread(
                    target=self.file_processor,
                    args=(task_queue, translator, self, progress_per_file),
                    daemon=True
                )
                t.start()
                workers.append(t)

            # 等待所有任务完成
            task_queue.join()

            if self.running:
                total_time = time.time() - start_time
                avg_speed = file_count / max(total_time, 0.001)

                # 确保进度条完成
                self.progress_value = 100

                self.log_queue.put(("-" * 70, "info"))
                self.log_queue.put((f"处理完成! 共处理 {file_count} 个文件", "info"))
                self.log_queue.put((f"总耗时: {total_time:.2f} 秒 | 平均速度: {avg_speed:.1f} 文件/秒", "info"))
                self.log_queue.put((f"翻译后的文件保存在: {os.path.abspath(target_dir)}", "info"))
                self.log_queue.put(("=" * 70, "info"))
                self.status_var.set(f"完成! 处理了 {file_count} 个文件")
            else:
                self.log_queue.put(("用户中断翻译过程", "info"))
                self.status_var.set("已停止")

        except Exception as e:
            self.log_queue.put((f"处理过程中发生错误: {str(e)}", "error"))
            messagebox.showerror("处理错误", f"发生错误:\n{str(e)}")
        finally:
            self.running = False
            self.start_button.config(state="enabled")
            self.stop_button.config(state="disabled")


if __name__ == "__main__":
    root = tk.Tk()
    app = TranslationApp(root)
    root.mainloop()